package nl.weeaboo.sh.editor;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JPanel;

import nl.weeaboo.sh.editor.area.ChangeListener;
import nl.weeaboo.sh.model.CharaImageModel;
import nl.weeaboo.sh.model.DamageRect;
import timon.common.components.DirectValidationField;
import timon.common.components.property.PropertyModel;
import timon.common.components.property.PropertyPanel;
import timon.common.components.property.editor.StringPropertyEditor;

@SuppressWarnings("serial")
public class HitBoxPropertyEditor extends JPanel {

	private CharaImageModel image;
	private List<ChangeListener> listeners;
	
	private DirectValidationField idField;
	private JComponent mainPanel;
	private PropertyPanel propertyPanel;
	private PropertyModel propertyModel;
	
	public HitBoxPropertyEditor(final Collection<CharaImageModel> charaImages,
			JComponent listPanel, JComponent modePanel)
	{
		listeners = new LinkedList<ChangeListener>();		
		propertyPanel = new PropertyPanel();
		
		idField = new DirectValidationField() {
			protected boolean isValid(String text) {
				if (image == null) return true;
				for (CharaImageModel i : charaImages) {
					if (image != i && text.equals(i.id)) return false;
				}
				return true;
			}
			protected void onValidTextEntered(String text) {
				if (image == null) return;
				image.id = text;
			}			
		};

		setPreferredSize(new Dimension(220, 200));
		setLayout(new BorderLayout(5, 10));
		add(listPanel, BorderLayout.NORTH);
		add(mainPanel = createMainPanel(), BorderLayout.CENTER);
		add(modePanel, BorderLayout.SOUTH);
		
		mainPanel.setVisible(false);
	}
	public void dispose() {
		propertyPanel.dispose();
	}
	
	//Functions		
	protected JPanel createMainPanel() {
		JPanel panel = new JPanel(new BorderLayout(5, 5));
		panel.add(propertyPanel, BorderLayout.CENTER);
		return panel;
	}
	
	public void addChangeListener(ChangeListener l) {
		listeners.add(l);
	}
	public void removeChangeListener(ChangeListener l) {
		listeners.remove(l);
	}
	
	protected void fireImageChanged(final CharaImageModel image) {
		ChangeListener ls[] = listeners.toArray(new ChangeListener[listeners.size()]);
		for (ChangeListener l : ls) {
			l.onChanged(image);
		}
	}

	//Getters
	public CharaImageModel getSelectedImage() {
		return image;
	}
	
	//Setters
	public void setSelectedImage(CharaImageModel i) {
		image = i;

		mainPanel.setVisible(image != null);			
		
		propertyModel = new PropertyModel();
		if (image != null) {
			propertyModel.addProperty("CharaImageModel.id", "ID", image.id, String.class);				
			propertyModel.addProperty("CharaImageModel.anchorX", "anchorX", image.anchor.x, Integer.class);				
			propertyModel.addProperty("CharaImageModel.anchorY", "anchorY", image.anchor.y, Integer.class);				
			propertyModel.addProperty("CharaImageModel.imageBoundsX", "imageX", image.imageBounds.x, Integer.class);				
			propertyModel.addProperty("CharaImageModel.imageBoundsY", "imageY", image.imageBounds.y, Integer.class);				
			propertyModel.addProperty("CharaImageModel.imageBoundsWidth", "imageWidth", image.imageBounds.width, Integer.class);				
			propertyModel.addProperty("CharaImageModel.imageBoundsHeight", "imageHeight", image.imageBounds.height, Integer.class);

			int t;

			propertyModel.addGroup("damageRects", "Damage Rects");
			t = 0;
			for (DamageRect dr : image.damageRects) {
				propertyModel.addToGroup("damageRects", "CharaImageModel.damageKnockbackX"+t, "knockbackX"+t, dr.knockbackX, Integer.class);				
				propertyModel.addToGroup("damageRects", "CharaImageModel.damageKnockbackY"+t, "knockbackY"+t, dr.knockbackY, Integer.class);				
				propertyModel.addToGroup("damageRects", "CharaImageModel.damageDamage"+t, "damage"+t, dr.damage, Integer.class);
				t++;
			}

			propertyModel.addGroup("splashRects", "Splash Rects");
			t = 0;
			for (DamageRect dr : image.splashRects) {
				propertyModel.addToGroup("splashRects", "CharaImageModel.splashKnockbackX"+t, "knockbackX"+t, dr.knockbackX, Integer.class);				
				propertyModel.addToGroup("splashRects", "CharaImageModel.splashKnockbackY"+t, "knockbackY"+t, dr.knockbackY, Integer.class);				
				propertyModel.addToGroup("splashRects", "CharaImageModel.splashDamage"+t, "damage"+t, dr.damage, Integer.class);
				t++;
			}
			
			propertyModel.setEditor("CharaImageModel.id", new StringPropertyEditor(idField));				
		}
		propertyPanel.setModel(propertyModel);									
		propertyModel.addPropertyListener(new PropertyModelListener(image));
	}
	
	//Inner Classes
	private class PropertyModelListener implements PropertyChangeListener {
		
		private final CharaImageModel selected;
		
		public PropertyModelListener(CharaImageModel s) {
			this.selected = s;
		}
		
		public void propertyChange(PropertyChangeEvent event) {
			if (selected == null) {
				return;
			}
			
			String pname = event.getPropertyName();
			if ("CharaImageModel.id".equals(pname)) {
				image.id = (String)event.getNewValue();
			} else if ("CharaImageModel.anchorX".equals(pname)) {
				image.anchor.x = (Integer)event.getNewValue();
			} else if ("CharaImageModel.anchorY".equals(pname)) {
				image.anchor.y = (Integer)event.getNewValue();
			} else if ("CharaImageModel.imageBoundsX".equals(pname)) {
				image.imageBounds.x = (Integer)event.getNewValue();
			} else if ("CharaImageModel.imageBoundsY".equals(pname)) {
				image.imageBounds.y = (Integer)event.getNewValue();
			} else if ("CharaImageModel.imageBoundsWidth".equals(pname)) {
				image.imageBounds.width = (Integer)event.getNewValue();
			} else if ("CharaImageModel.imageBoundsHeight".equals(pname)) {
				image.imageBounds.height = (Integer)event.getNewValue();
			} else if (pname.startsWith("CharaImageModel.damageKnockbackX")) {
				int index = Integer.parseInt(pname.substring("CharaImageModel.damageKnockbackX".length()));
				image.damageRects.get(index).knockbackX = (Integer)event.getNewValue();
			} else if (pname.startsWith("CharaImageModel.damageKnockbackY")) {
				int index = Integer.parseInt(pname.substring("CharaImageModel.damageKnockbackY".length()));
				image.damageRects.get(index).knockbackY = (Integer)event.getNewValue();
			} else if (pname.startsWith("CharaImageModel.damageDamage")) {
				int index = Integer.parseInt(pname.substring("CharaImageModel.damageDamage".length()));
				image.damageRects.get(index).damage = (Integer)event.getNewValue();
			} else if (pname.startsWith("CharaImageModel.splashKnockbackX")) {
				int index = Integer.parseInt(pname.substring("CharaImageModel.splashKnockbackX".length()));
				image.splashRects.get(index).knockbackX = (Integer)event.getNewValue();
			} else if (pname.startsWith("CharaImageModel.splashKnockbackY")) {
				int index = Integer.parseInt(pname.substring("CharaImageModel.splashKnockbackY".length()));
				image.splashRects.get(index).knockbackY = (Integer)event.getNewValue();
			} else if (pname.startsWith("CharaImageModel.splashDamage")) {
				int index = Integer.parseInt(pname.substring("CharaImageModel.splashDamage".length()));
				image.splashRects.get(index).damage = (Integer)event.getNewValue();
			}
			
			fireImageChanged(selected);
		}
	}

}
